#import "MCTip.h"
CGFloat const MCMaxOffset = 1000000.f;
typedef NS_ENUM(NSInteger, MCTipAnimation) {
    MCTipAnimationFade,
    MCTipAnimationZoom,
    MCTipAnimationZoomOut,
    MCTipAnimationZoomIn
};
@interface MCBackgroundView : UIView
@end
@interface MCTip ()
@property (nonatomic, assign) CGPoint offset;
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, strong) UIColor *textColor;

@property (nonatomic, assign) CGSize minSize;
@property (nonatomic, assign) CGFloat margin;
@property (nonatomic, assign) BOOL removeFromSuperViewOnHide;

@property (nonatomic, strong) UIView *topSpacer;
@property (nonatomic, strong) UIView *bottomSpacer;
@property (nonatomic, strong) NSArray *bgViewConstraints;
@property (nonatomic, strong) NSArray *paddingConstraints;
@property (nonatomic, weak) NSTimer *hideDelayTimer;
@property (nonatomic, strong ) UIView *backgroundView;
@property (nonatomic, assign, getter=hasFinished) BOOL finished;
@end

@implementation MCTip
// - (void)dealloc { NSLog(@"dealloc"); }
- (id)initWithView:(UIView *)view {
    return [self initWithFrame:view.bounds];
}
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        _margin = 15.0f;
        _font = [UIFont boldSystemFontOfSize:15];
        self.backgroundColor = [UIColor clearColor];
        _textColor = [UIColor colorWithWhite:1.f alpha:1.f];
        [self setupSubViews];
    }
    return self;
}
+ (void)showHint:(NSString *)hint {
    if (hint.length<1) { return; }
    dispatch_async(dispatch_get_main_queue(), ^{
        MCTip *tip = [MCTip showHUDAddedTo:[UIApplication sharedApplication].delegate.window];
        tip.label.text = hint;
        tip.offset = CGPointMake(0, 0);
        [tip hideAfterDelay:1.8f];
    });
}
+ (void)showHint:(NSString *)hint yOffset:(float)yOffset {
    if (hint.length<1) { return; }
    dispatch_async(dispatch_get_main_queue(), ^{
        MCTip *tip = [MCTip showHUDAddedTo:[UIApplication sharedApplication].delegate.window];
        tip.label.text = hint;
        tip.offset = CGPointMake(0, yOffset);
        [tip hideAfterDelay:1.8f];
    });
}
+ (instancetype)showHUDAddedTo:(UIView *)view {
    MCTip *hud = [[self alloc] initWithView:view];
    hud.offset = CGPointMake(0.f, MCMaxOffset);
    hud.removeFromSuperViewOnHide = YES;
    [view addSubview:hud];
    [hud show];
    return hud;
}
- (void)hideAfterDelay:(NSTimeInterval)delay {
    [self.hideDelayTimer invalidate];
    NSTimer *timer = [NSTimer timerWithTimeInterval:delay target:self selector:@selector(hide) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.hideDelayTimer = timer;
}
- (void)setupSubViews {
    MCBackgroundView *backgroundView = [[MCBackgroundView alloc] init];
    backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
    backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    backgroundView.backgroundColor = [UIColor colorWithWhite:0. alpha:0.6];
    backgroundView.layer.cornerRadius = 5.f;
    [self addSubview:backgroundView];
    _backgroundView = backgroundView;

    UILabel *label = [[UILabel alloc] init];
    label.adjustsFontSizeToFitWidth = NO;
    label.textAlignment = NSTextAlignmentCenter;
    label.font = self.font;
    label.textColor = self.textColor;
    label.backgroundColor = [UIColor clearColor];
    _label = label;

    label.translatesAutoresizingMaskIntoConstraints = NO;
    [label setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal];
    [label setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical];
    [backgroundView addSubview:label];

    UIView *topSpacer = [[UIView alloc] init];
    topSpacer.hidden = YES;
    topSpacer.translatesAutoresizingMaskIntoConstraints = NO;
    [backgroundView addSubview:topSpacer];
    _topSpacer = topSpacer;

    UIView *bottomSpacer = [[UIView alloc] init]    ;
    bottomSpacer.hidden = YES;
    bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO;
    [backgroundView addSubview:bottomSpacer];
    _bottomSpacer = bottomSpacer;
}
- (void)setOffset:(CGPoint)offset {
    if (!CGPointEqualToPoint(offset, _offset)) {
        _offset = offset;
        [self setNeedsUpdateConstraints];
    }
}

- (void)show {
    self.finished = NO;
    [self showUsingAnimation];
}
- (void)showUsingAnimation {
    [self.backgroundView.layer removeAllAnimations];
    [self.hideDelayTimer invalidate];
    self.alpha = 1.f;
    [self animateIn:YES withType:MCTipAnimationFade completion:NULL];
}

- (void)animateIn:(BOOL)animatingIn withType:(MCTipAnimation)type completion:(void(^)(BOOL finished))completion {
    if (type == MCTipAnimationZoom) {
        type = animatingIn ? MCTipAnimationZoomIn : MCTipAnimationZoomOut;
    }
    CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f);
    CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f);
    UIView *backgroundView = self.backgroundView;
    if (animatingIn && backgroundView.alpha == 0.f && type == MCTipAnimationZoomIn) {
        backgroundView.transform = small;
    } else if (animatingIn && backgroundView.alpha == 0.f && type == MCTipAnimationZoomOut) {
        backgroundView.transform = large;
    }
    dispatch_block_t animations = ^{
        if (animatingIn) {
            backgroundView.transform = CGAffineTransformIdentity;
        }else if (!animatingIn && type == MCTipAnimationZoomOut) {
            backgroundView.transform = small;
        }
        CGFloat alpha = animatingIn ? 1.f : 0.f;
        backgroundView.alpha = alpha;
    };
    [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion];
}
- (void)hide {
    self.finished = YES;
    [self.hideDelayTimer invalidate];
    [self animateIn:NO withType:MCTipAnimationZoom completion:^(BOOL finished) {
        [self done];
    }];
}
- (void)done {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.hasFinished) {
            self.alpha = 0.0f;
            if (self.removeFromSuperViewOnHide) {
                [self removeFromSuperview];
            }
        }
    });
}
- (void)updateConstraints {
    UIView *bgView = self.backgroundView;
    UIView *topSpacer = self.topSpacer;
    UIView *bottomSpacer = self.bottomSpacer;
    CGFloat margin = self.margin;
    NSMutableArray *bgViewConstraints = [NSMutableArray array];
    NSDictionary *metrics = @{@"margin": @(margin)};
    NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.bottomSpacer, nil];
    [self removeConstraints:self.constraints];
    [topSpacer removeConstraints:topSpacer.constraints];
    [bottomSpacer removeConstraints:bottomSpacer.constraints];

    NSMutableArray *centeringConstraints = [NSMutableArray array];
    [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bgView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:self.offset.x]];
    [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bgView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:self.offset.y]];
    for (NSLayoutConstraint *constraint in centeringConstraints) {
        constraint.priority = 998.f;
    }
    [self addConstraints:centeringConstraints];

    NSMutableArray *sideConstraints = [NSMutableArray array];
    [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bgView]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bgView)]];
    [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bgView]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bgView)]];
    for (NSLayoutConstraint *constraint in sideConstraints) {
        constraint.priority = 999.f;
    }
    [self addConstraints:sideConstraints];

    CGSize minimumSize = self.minSize;
    if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) {
        NSMutableArray *minSizeConstraints = [NSMutableArray array];
        [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bgView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]];
        [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bgView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]];
        for (NSLayoutConstraint *constraint in minSizeConstraints) {
            constraint.priority = 997.f;
        }
        [bgViewConstraints addObjectsFromArray:minSizeConstraints];
    }

    [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]];
    [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]];
    [bgViewConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]];

    NSMutableArray *paddingConstraints = [NSMutableArray new];
    [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
        
        [bgViewConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]];
        
        [bgViewConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]];
        
        if (idx == 0) {
            [bgViewConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
        } else if (idx == subviews.count - 1) {
            [bgViewConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bgView attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
        }
        if (idx > 0) {
            NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f];
            [bgViewConstraints addObject:padding];
            [paddingConstraints addObject:padding];
        }
    }];
    [bgView addConstraints:bgViewConstraints];
    self.bgViewConstraints = bgViewConstraints;
    self.paddingConstraints = [paddingConstraints copy];
    [super updateConstraints];
}
@end

@implementation MCBackgroundView
- (CGSize)intrinsicContentSize {
    return CGSizeZero;
}
@end
